package com.lzc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lzc.domain.BLaiLocation;
import com.lzc.domain.City;
import com.lzc.domain.Province;
import com.lzc.domain.MigrationProgress;
import com.lzc.mapper.BLaiLocationMapper;
import com.lzc.model.vo.LocationInfo;
import com.lzc.service.BLaiLocationService;
import com.lzc.service.DataMigrationService;
import com.lzc.service.ProvinceService;
import com.lzc.service.CityService;
import com.lzc.service.TranslationService;
import com.lzc.service.MigrationProgressService;
import com.lzc.util.translate.TransApi;
import com.lzc.util.translate.dto.BaiduTransResponse;
import com.lzc.util.translate.dto.TransResultItem;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 数据迁移服务实现类
 * 针对8GB Windows电脑优化，高效处理大量数据迁移
 */
@Slf4j
@Service
public class DataMigrationServiceImpl implements DataMigrationService {

    @Autowired
    private BLaiLocationService bLaiLocationService; // 源表服务：分页拉取 b_lai_location 数据
    
    @Autowired
    private ProvinceService provinceService; // 目标表服务：批量写入 province 数据
    
    @Autowired
    private CityService cityService; // 目标表服务：批量写入 city 数据
    
//    @Autowired
//    private BLaiLocationMapper bLaiLocationMapper; // 若需自定义SQL可使用，但当前以通用Service为主
//
//    @Autowired
//    private TranslationService translationService; // 简易中英互译服务，用于生成多语言字段

    @Autowired
    private MigrationProgressService migrationProgressService; // 迁移进度服务：断点续跑的核心依赖


    @Autowired
    private ChatClient chatClient;
    
    // 用于统计迁移记录数（包含续跑前累计数）
    private final AtomicLong migratedCount = new AtomicLong(0);

    // 迁移任务名：用于在 migration_progress 表中区分不同迁移任务
    private static final String TASK_NAME = "BLaiLocation_to_Province";

    // 在平台申请的APP_ID 详见 https://fanyi-api.baidu.com/api/trans/product/desktop?req=developer
    private static final String APP_ID = "20250905002447045";
    private static final String SECURITY_KEY = "ov5RW_QQwZj7Nqpsndlm";

    /**
     * 执行从源表 b_lai_location 到目标表 province/city 的批量迁移
     */
    @Override
    public long migrateData(int batchSize) {
        log.info("开始数据迁移，批处理大小: {}", batchSize);
        long totalCount = getSourceDataCount();
        log.info("源表总记录数: {}", totalCount);
        if (totalCount == 0) {
            log.warn("源表无数据，跳过迁移");
            return 0;
        }
        migratedCount.set(0);

        MigrationProgress progress = migrationProgressService.getOrCreateProgress(
                TASK_NAME, "b_lai_location", "province_city", totalCount, batchSize
        );
        long lastMaxProcessedId = progress.getMaxProcessedId() == null ? 0L : progress.getMaxProcessedId();
        long alreadyProcessedCount = progress.getProcessedCount() == null ? 0L : progress.getProcessedCount();
        if (alreadyProcessedCount > 0 || lastMaxProcessedId > 0) {
            log.info("检测到已有进度，将从ID大于 {} 处续跑，已处理 {} 条", lastMaxProcessedId, alreadyProcessedCount);
            migratedCount.set(alreadyProcessedCount);
        }
        try {
            long currentCursorId = lastMaxProcessedId;
            final Page<BLaiLocation> page = new Page<>(1, batchSize);
            while (true) {
                LambdaQueryWrapper<BLaiLocation> wrapper = new LambdaQueryWrapper<BLaiLocation>()
                        .gt(BLaiLocation::getId, currentCursorId)
                        .orderByAsc(BLaiLocation::getId);
                IPage<BLaiLocation> result = bLaiLocationService.page(page, wrapper);
                List<BLaiLocation> sourceData = result.getRecords();
                if (sourceData == null || sourceData.isEmpty()) {
                    break;
                }

                List<Province> provinceData = new ArrayList<>(sourceData.size());
                List<City> cityData = new ArrayList<>(sourceData.size());
                for (BLaiLocation source : sourceData) {
//                    buildProvinceAndCity(source, provinceData, cityData);
                    buildProvinceAndCityByAI(source, provinceData, cityData);
                }

                saveProvinceBatch(provinceData, batchSize);
                saveCityBatch(cityData, batchSize);

                migratedCount.addAndGet(provinceData.size());
                currentCursorId = sourceData.get(sourceData.size() - 1).getId().longValue();
                migrationProgressService.updateProgress(TASK_NAME, currentCursorId, migratedCount.get());
            }
            migrationProgressService.completeTask(TASK_NAME);
            long finalCount = migratedCount.get();
            log.info("数据迁移完成，共迁移 {} 条记录", finalCount);
            return finalCount;
        } catch (Exception e) {
            log.error("迁移过程中发生错误: {}", e.getMessage(), e);
            migrationProgressService.failTask(TASK_NAME, e.getMessage());
            throw e;
        }
    }


    /**
     *  调用ai大模型进行数据处理
     *
     * @param source
     * @param provinceData
     * @param cityData
     */
    private void buildProvinceAndCityByAI(BLaiLocation source, List<Province> provinceData, List<City> cityData) {
        if (source == null) return;
        String prompt = JSONUtil.toJsonStr(source);
        String content = chatClient.prompt()
                .user(prompt)
                .call()
                .content();
        LocationInfo locationInfo = JSONUtil.toBean(content, LocationInfo.class);
        Province province = locationInfo.getProvince();
        City city = locationInfo.getCity();
        if (province == null || city == null) return;
        province.setId((long) source.getId());
        city.setId((long) source.getId());
        provinceData.add(province);
        cityData.add(city);
    }




    /**
     * 使用一次百度翻译调用，同时构建 Province 与 City，并加入对应列表。
     * - 仅翻译 country/province/city 为中文；其余字段置空。
     * - 失败或部分缺项时回退原文，保证流程不中断。
     */
    private void buildProvinceAndCity(BLaiLocation source, List<Province> provinces, List<City> cities) {
        // 空保护：源记录为空直接返回
        if (source == null) return;

        // 取出并清洗 country（允许为空串）
        String rawCountry = source.getCountry() == null ? "" : source.getCountry().trim();
        // 取出并清洗 province（允许为空串）
        String rawProvince = source.getProvince() == null ? "" : source.getProvince().trim();
        // 取出并清洗 city（允许为空串）
        String rawCity = source.getCity() == null ? "" : source.getCity().trim();
        // 全部为空则无需翻译与构建
        if (rawCountry.isEmpty() && rawProvince.isEmpty() && rawCity.isEmpty()) return;

        // 待翻译文本集合（按加入顺序决定返回映射位置）
        List<String> parts = new ArrayList<>(3);
        // 记录每个字段在 parts 中的索引，-1 表示该字段为空未加入
        int idxCountry = -1, idxProvince = -1, idxCity = -1;
        // country 非空则加入，并记录索引
        if (!rawCountry.isEmpty()) { idxCountry = parts.size(); parts.add(rawCountry); }
        // province 非空则加入，并记录索引
        if (!rawProvince.isEmpty()) { idxProvince = parts.size(); parts.add(rawProvince); }
        // city 非空则加入，并记录索引
        if (!rawCity.isEmpty()) { idxCity = parts.size(); parts.add(rawCity); }
        // 若没有任何需要翻译的内容，直接返回
        if (parts.isEmpty()) return;

        // 以换行符拼接为一次 q 参数；底层 HttpGet 负责 URL encode
        String q = String.join("\n", parts);
        // 构造翻译客户端（如需进一步优化可上移复用）
        TransApi api = new TransApi(APP_ID, SECURITY_KEY);
        // 执行翻译：auto -> zh
        BaiduTransResponse resp = api.getTransResultObject(q, "auto", "zh");

        // 默认回退为原文，避免翻译失败导致空值
        String cnCountry = rawCountry;
        String cnProvince = rawProvince;
        String cnCity = rawCity;
        // 有翻译结果则按索引映射回各字段
        if (resp != null && resp.getTrans_result() != null && !resp.getTrans_result().isEmpty()) {
            List<TransResultItem> list = resp.getTrans_result();
            if (idxCountry >= 0 && idxCountry < list.size()) cnCountry = list.get(idxCountry).getDst();
            if (idxProvince >= 0 && idxProvince < list.size()) cnProvince = list.get(idxProvince).getDst();
            if (idxCity >= 0 && idxCity < list.size()) cnCity = list.get(idxCity).getDst();
        }

        // 构建 Province：仅设置所需字段，其余置空
        Province p = new Province();
        // 赋值主键（与源表ID保持一致），满足 IdType.INPUT 的要求
        p.setId((long) source.getId());
        // 不再从源ID赋值，交由数据库自增生成
        p.setCountry(cnCountry);
        // 省（中文）
        p.setCnshortname(cnProvince);
        p.setCnfullname(cnProvince);
        // 英文字段暂空
        p.setEnshortname("");
        p.setEnfullname("");
        // 编码后续按需生成，这里置空
        p.setCode("");
        // 放入省份结果集
        provinces.add(p);

        // 构建 City：仅设置所需字段，其余置空
        City c = new City();
        // 赋值主键（与源表ID保持一致），满足 IdType.INPUT 的要求
        c.setId((long) source.getId());
        // 不再从源ID赋值，交由数据库自增生成
        c.setCountry(cnCountry);
        // 市（中文）
        c.setCnshortname(cnCity);
        c.setCnfullname(cnCity);
        // 英文字段暂空
        c.setEnshortname("");
        c.setEnfullname("");
        // 编码后续按需生成，这里置空
        c.setCode("");
        // 放入城市结果集
        cities.add(c);
    }

    /**
     * 省份批量保存
     */
    @Transactional(rollbackFor = Exception.class)
    protected void saveProvinceBatch(List<Province> targetData, int batchSize) {
        if (targetData == null || targetData.isEmpty()) {
            return;
        }
        provinceService.saveOrUpdateBatch(targetData, batchSize);
    }

    /**
     * 城市批量保存
     */
    @Transactional(rollbackFor = Exception.class)
    protected void saveCityBatch(List<City> targetData, int batchSize) {
        if (targetData == null || targetData.isEmpty()) {
            return;
        }
        cityService.saveOrUpdateBatch(targetData, batchSize);
    }

    @Override
    public long getSourceDataCount() {
        return bLaiLocationService.count();
    }

    @Override
    public void clearTargetData() {
        log.info("开始清理目标表数据");
        provinceService.remove(null);
        // 同步重置任务进度，便于重新全量迁移
        migrationProgressService.resetTask(TASK_NAME);
        log.info("目标表数据清理完成");
    }
}
